using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Transactions;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;
using OracleInternal.ServiceObjects;

namespace OracleInternal.MTS
{
	internal abstract class DTCPSPEManager : PSPEManager
	{
		internal static object s_dtcTxCreator;

		internal const int s_txnGuidSize = 16;

		private object m_dtcTxWrapper;

		private static MethodInfo CreateDTCTxWrapper;

		private static MethodInfo Commit;

		private static MethodInfo Abort;

		private static MethodInfo Dispose;

		static DTCPSPEManager()
		{
			try
			{
				Assembly assembly = Assembly.Load($"Oracle.ManagedDataAccessDTC, Version={ConfigBaseClass.m_assemblyVersion}, Culture=neutral, PublicKeyToken=89b483f429c47342");
				Type? type = assembly.GetType("OracleInternal.MTS.CPP.MDtcTxCreator");
				s_dtcTxCreator = type!.GetConstructor(Type.EmptyTypes)!.Invoke(null);
				CreateDTCTxWrapper = type!.GetMethod("CreateDTCTxWrapper");
				Type? type2 = assembly.GetType("OracleInternal.MTS.CPP.MDtcTxWrapper");
				Commit = type2!.GetMethod("Commit");
				Abort = type2!.GetMethod("Abort");
				Dispose = type2!.GetMethod("Dispose");
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268439552, OracleTraceClassName.DTCPSPEManager, OracleTraceFuncName.cctor, ex);
				throw;
			}
		}

		internal DTCPSPEManager(OracleConnectionImpl connImpl, Transaction txn, MTSTxnRM txnRM, MTSTxnBranch txnBranch)
			: base(connImpl, txn, txnRM, txnBranch)
		{
		}

		internal override byte[] InternalPromote(out Guid txnGuid)
		{
			byte[] array = null;
			byte[] array2 = null;
			IntPtr intPtr = IntPtr.Zero;
			IntPtr intPtr2 = IntPtr.Zero;
			int num = 0;
			txnGuid = Guid.Empty;
			try
			{
				object[] array3 = new object[3]
				{
					num,
					intPtr,
					intPtr2
				};
				m_dtcTxWrapper = CreateDTCTxWrapper.Invoke(s_dtcTxCreator, array3);
				num = (int)array3[0];
				intPtr = (IntPtr)array3[1];
				intPtr2 = (IntPtr)array3[2];
				array = new byte[num];
				array2 = new byte[16];
				Marshal.Copy(intPtr, array, 0, num);
				Marshal.Copy(intPtr2, array2, 0, 16);
				txnGuid = new Guid(array2);
				return array;
			}
			finally
			{
				try
				{
					Marshal.FreeCoTaskMem(intPtr);
				}
				catch
				{
				}
				try
				{
					Marshal.FreeCoTaskMem(intPtr2);
				}
				catch
				{
				}
			}
		}

		internal override bool InternalCommit()
		{
			try
			{
				if (m_mtsTxnRM.m_enlistedState == EnlistedState.Local)
				{
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						string[] array = new string[1];
						Guid rMGuid = m_mtsTxnRM.m_RMGuid;
						array[0] = "Invoking MTSTxnRM.EnlistToSysTransaction() MTSTxnRM : " + rMGuid.ToString() + " RM EnlistedState = " + m_mtsTxnRM.m_enlistedState;
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.DTCPSPEManager, OracleTraceFuncName.InternalCommit, array);
					}
					m_mtsTxnRM.EnlistToSysTransaction();
				}
				int num = (int)Commit.Invoke(m_dtcTxWrapper, null);
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.DTCPSPEManager, OracleTraceFuncName.InternalCommit, "PSPEManager.SinglePhaseCommit(): DTC Transaction committed HRESULT = " + num + " Local TxnID = " + m_sysTxn.TransactionInformation.LocalIdentifier + "\tTxnID = " + m_sysTxn.TransactionInformation.DistributedIdentifier.ToString());
				}
				return (num == 0) ? true : false;
			}
			finally
			{
				try
				{
					Dispose.Invoke(m_dtcTxWrapper, null);
				}
				catch
				{
				}
				m_dtcTxWrapper = null;
			}
		}

		internal override bool InternalRollback()
		{
			try
			{
				if (m_mtsTxnRM.m_enlistedState == EnlistedState.Local)
				{
					try
					{
						m_mtsTxnRM.doAbort();
					}
					catch (Exception ex)
					{
						try
						{
							OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268439552, OracleTraceClassName.DTCPSPEManager, OracleTraceFuncName.InternalRollback, ex);
						}
						catch
						{
						}
						try
						{
							Abort.Invoke(m_dtcTxWrapper, null);
						}
						catch
						{
						}
						throw;
					}
					finally
					{
						try
						{
							ReleaseRM(m_connStr);
						}
						catch
						{
						}
					}
				}
				return ((int)Abort.Invoke(m_dtcTxWrapper, null) == 0) ? true : false;
			}
			finally
			{
				try
				{
					Dispose.Invoke(m_dtcTxWrapper, null);
				}
				catch
				{
				}
				m_dtcTxWrapper = null;
			}
		}

		internal override void InternalHandlePromoteError()
		{
		}
	}
}
